using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;

using System.Xml;
using System.IO;
using System.IO.Packaging;

using LogAnalyzerIIS.Exporters;
using LogAnalyzerIIS.WizardForms;
using LogAnalyzerIIS.Objects;
using LogAnalyzerIIS.Properties;

namespace LogAnalyzerIIS
{
	public partial class SideBar : UserControl
	{
		public SideBar()
		{
			InitializeComponent();

			cbExportReportTo.SelectedIndex = 0;
			cbExportLogTo.SelectedIndex = 0;
			lblSessionName.Text = "";
		}

		/// <summary>
		/// Loads all XML files in the specified folder as session properties files.
		/// </summary>
		public void LoadSessions(string selectSessionName)
		{
			string sessionPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + Resources.APPLICATION_FOLDER_NAME + "\\" + Resources.SESSIONS_FOLDER_NAME;

			if (!Directory.Exists(sessionPath))
				Directory.CreateDirectory(sessionPath);

			string[] filePaths = Directory.GetFiles(sessionPath, "*.xml");

			// add the sessions to the combo box
			lbSessions.Items.Clear();

			foreach (string sessionFilePath in filePaths)
			{
				// load the session and add to the sessions list
				Session session = new Session();
				session.LoadSessionFromFile(sessionFilePath);
				lbSessions.Items.Add(session);
			}

			if (selectSessionName == "")
			{
				// if sessions list isn't empty, select its first element
				if (lbSessions.Items.Count > 0)
					lbSessions.SelectedIndex = 0;
			}
			else
				lbSessions.SelectedIndex = lbSessions.FindStringExact(selectSessionName);
		}

		private void ShowWizard(DemoWizard.MainWizard.StartPage showState)
		{
			if (lbSessions.SelectedItem != null)
			{
				// loading the
				//Wizard wiz = new Wizard(showState, lbSessions.SelectedItem as Session);
				DemoWizard.MainWizard wiz = new LogAnalyzerIIS.DemoWizard.MainWizard(showState, lbSessions.SelectedItem as Session);

				wiz.ShowDialog();

				LoadSessionControlsFromSelectedSession();
			}
		}

		/// <summary>
		/// 'Run Wizard' button click handler
		/// </summary>
		private void btnRunWizard_Click(object sender, EventArgs e)
		{
			if (lbSessions.SelectedIndex > -1)
				ShowWizard(DemoWizard.MainWizard.StartPage.Servers);
		}

		private void LoadSessionControlsFromSelectedSession()
		{
			// enable the group
			grpSession.Enabled = true;

			// get item from the sessions list
			Session session = lbSessions.SelectedItem as Session;
			lblSessionName.Text = session.Name;

			// populate report files list
			lbReportFiles.Items.Clear();
			foreach (FilePath filePath in session.ReportFilepaths)
			{
				ListViewItem lvi = new ListViewItem(new string[] { filePath.ToString() });
				lvi.Tag = filePath;
				lbReportFiles.Items.Add(lvi);
			}

			// populate log files list
			lbLogFiles.Items.Clear();
			foreach (ServerRecord server in session.ServerRecords)
			{
				foreach (WebApplication application in server.WebApplications)
				{
					foreach (FilePath filePath in application.LogFiles)
					{
						ListViewItem lvi = new ListViewItem(new string[] { filePath.ToString(), application.Name });
						lvi.Tag = filePath;
						lbLogFiles.Items.Add(lvi);
					}
				}
			}

			lbLogFiles.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
			btnDeleteSession.Enabled = true;

			lbLogFiles_SelectedIndexChanged(lbLogFiles, null);
		}

		private void lbSessions_SelectedIndexChanged(object sender, EventArgs e)
		{
			// if item has been selected
			if (lbSessions.SelectedIndex > -1)
				LoadSessionControlsFromSelectedSession();
			else
			{
				// if item has been deselected, disable controls
				btnDeleteSession.Enabled = false;
				grpSession.Enabled = false;
			}
		}

		private void btnDeleteSession_Click(object sender, EventArgs e)
		{
			if (lbSessions.SelectedIndex < 0)
				return;

			// delete session properties file
			File.Delete((lbSessions.SelectedItem as Session).SaveLocation);

			// remove session from the list
			lbSessions.Items.RemoveAt(lbSessions.SelectedIndex);
		}

		private void btnNewSession_Click(object sender, EventArgs e)
		{
			// create a new save same
			Session session = new Session();

			// generate session properties file name depending on current date/time
			string filename = "Session " + DateTime.Now.ToString() + ".xml";
			string newfn = "";

			// get rid of invalid characters in the generated filename
			char[] c = Path.GetInvalidFileNameChars();

			for (int i = 0; i < filename.Length; i++)
			{
				bool invalid = false;

				// if invalid character found, change it to whitespace
				for (int j = 0; j < c.Length; j++)
				{
					if (filename[i] == c[j])
					{
						invalid = true;
						break;
					}
				}

				if (invalid)
					newfn += ' ';
				else
					newfn += filename[i];
			}

			session.SaveLocation = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + Properties.Resources.APPLICATION_FOLDER_NAME + "\\" + Properties.Resources.SESSIONS_FOLDER_NAME + "\\" + newfn;


			// get list of session names to avoid duplicate names
			List<string> sessionNames = new List<string>();

			foreach (Session tempSession in lbSessions.Items)
				sessionNames.Add(tempSession.Name);

			// show the session form
			SessionForm sessionForms = new SessionForm(session, sessionNames);

			if (sessionForms.ShowDialog() == DialogResult.OK)
			{
				lbSessions.SelectedIndex = lbSessions.Items.Add(session);
				LoadSessionControlsFromSelectedSession();
				LoadSessions(session.Name);
			}
		}


		private void SideBar_VisibleChanged(object sender, EventArgs e)
		{
			// load sessions if sidebar becomes visible
			if (this.Visible)
				LoadSessions("");
		}

		private void btnOpenLogFile_Click(object sender, EventArgs e)
		{
			lbLogFiles_DoubleClick(lbLogFiles, null);
		}

		private void btnDeleteLogFile_Click(object sender, EventArgs e)
		{
			try
			{
				// delete selected log files
				while (lbLogFiles.SelectedItems.Count > 0)
				{
					if (lbLogFiles.SelectedItems[0] != null)
					{
						// remove log file reference from the WebApplication objects
						Session session = lbSessions.SelectedItem as Session;

						foreach (ServerRecord server in session.ServerRecords)
						{
							foreach (WebApplication application in server.WebApplications)
							{
								foreach (FilePath filePath in application.LogFiles)
								{
									if (filePath.FullPath == (lbLogFiles.SelectedItems[0].Tag as FilePath).FullPath)
									{
										application.LogFiles.Remove(filePath);
										break;
									}
								}
							}
						}
						// delete log file from the disk
						File.Delete((lbLogFiles.SelectedItems[0].Tag as FilePath).FullPath);

						lbLogFiles.Items.Remove(lbLogFiles.SelectedItems[0]);

						session.Save();
					}
				}

				lbLogFiles_SelectedIndexChanged(null, null);
			}
			catch
			{
				MessageBox.Show("Cannot delete file: possibly it is already open");
			}
		}


		private void lbLogFiles_DoubleClick(object sender, EventArgs e)
		{
			// open log file in Excel
			for (int i = 0; i < lbLogFiles.SelectedItems.Count; i++)
			{
				if (lbLogFiles.SelectedItems[i] != null)
				{
					try
					{
						Globals.ThisAddIn.Application.Workbooks.Open(
								(lbLogFiles.SelectedItems[i].Tag as FilePath).FullPath, Type.Missing, Type.Missing, Type.Missing,
								Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
								Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
					}
					catch
					{
						MessageBox.Show("Cannot open a file. Possible it was deleted.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					}
				}
			}
		}

		private void lbLogFiles_SelectedIndexChanged(object sender, EventArgs e)
		{
			// if log file has been selected, enable Open/Delete buttons, otherwise disable them
			if (lbLogFiles.SelectedIndices.Count > 0)
			{
				btnDeleteLogFile.Enabled = true;
				btnOpenLogFile.Enabled = true;
				cbExportLogTo.Enabled = true;
				btnExportLogFile.Enabled = true;
			}
			else
			{
				btnDeleteLogFile.Enabled = false;
				btnOpenLogFile.Enabled = false;
				cbExportLogTo.Enabled = false;
				btnExportLogFile.Enabled = false;
			}
		}

		private void lbLogFiles_KeyUp(object sender, KeyEventArgs e)
		{
			// handle log files opening/deleting using keyboard
			switch (e.KeyCode)
			{
				case Keys.Enter:
					// open files
					lbLogFiles_DoubleClick(null, null);
					break;
				case Keys.Delete:
					// delete files
					btnDeleteLogFile_Click(null, null);
					break;
			}
		}

		private void btnDeleteReportFile_Click(object sender, EventArgs e)
		{
			try
			{
				// delete report files
				while (lbReportFiles.SelectedItems.Count > 0)
				{
					if (lbReportFiles.SelectedItems[0] != null)
					{
						Session session = lbSessions.SelectedItem as Session;

						foreach (FilePath filePath in session.ReportFilepaths)
						{
							if (filePath.FullPath == (lbReportFiles.SelectedItems[0].Tag as FilePath).FullPath)
							{
								// remove report file from the session ouput files list
								session.ReportFilepaths.Remove(filePath);
								break;
							}
						}
						// delete report file from the disk
						File.Delete((lbReportFiles.SelectedItems[0].Tag as FilePath).FullPath);
						lbReportFiles.Items.Remove(lbReportFiles.SelectedItems[0]);

						// save the session
						session.Save();
					}
				}

				lbReportFiles_SelectedIndexChanged(null, null);
			}
			catch
			{
				MessageBox.Show("Cannot delete file: possibly it is already open");
			}
		}

		private void lbReportFiles_SelectedIndexChanged(object sender, EventArgs e)
		{
			// if items has been selected, enable Open/Delete buttons,
			// Export To combo box and Go button, otherwise disable them
			if (lbReportFiles.SelectedIndices.Count > 0)
			{
				btnDeleteReportFile.Enabled = true;
				btnOpenReportFile.Enabled = true;
				try
				{
					if (Path.GetExtension((lbReportFiles.SelectedItems[0].Tag as FilePath).FullPath) == ".xlsx")
					{
						btnExportReportFile.Enabled = true;
						cbExportReportTo.Enabled = true;
					}
					else
					{
						btnExportReportFile.Enabled = false;
						cbExportReportTo.Enabled = false;
					}
				}
				catch
				{
					btnExportReportFile.Enabled = false;
					cbExportReportTo.Enabled = false;
				}

			}
			else
			{
				btnDeleteReportFile.Enabled = false;
				btnOpenReportFile.Enabled = false;
				btnExportReportFile.Enabled = false;
				cbExportReportTo.Enabled = false;
			}
		}

		private void lbReportFiles_DoubleClick(object sender, EventArgs e)
		{
			// open selected in the report Files list files
			for (int i = 0; i < lbReportFiles.SelectedItems.Count; i++)
			{
				if (lbReportFiles.SelectedItems[i] != null)
				{
					try
					{
						string filePath = (lbReportFiles.SelectedItems[i].Tag as FilePath).FullPath;
						if (Path.GetExtension(filePath) == ".xlsx")
						{

							Globals.ThisAddIn.Application.Workbooks.Open(
									filePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
									Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
									Type.Missing,
									Type.Missing, Type.Missing, Type.Missing, Type.Missing);
						}
						else
							System.Diagnostics.Process.Start(filePath);

					}
					catch
					{
						MessageBox.Show("Cannot open a file. Possibly it was deleted.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					}
				}
			}
		}

		private void btnOpenReportFile_Click(object sender, EventArgs e)
		{
			lbReportFiles_DoubleClick(lbLogFiles, null);
		}

		private void lbReportFiles_KeyUp(object sender, KeyEventArgs e)
		{
			// handle report files opening/deleting using keyboard
			switch (e.KeyCode)
			{
				case Keys.Enter:
					// open files
					lbReportFiles_DoubleClick(null, null);
					break;
				case Keys.Delete:
					// delete files
					btnDeleteReportFile_Click(null, null);
					break;
			}
		}

		private void AddNewOutputToSession(Session session, string fileName)
		{
			FilePath filePath = new FilePath(fileName);
			bool outputExists = false;
			foreach (FilePath existingFilePath in session.ReportFilepaths)
			{
				if (existingFilePath.FullPath == filePath.FullPath)
				{
					outputExists = true;
					break;
				}

			}
			if (!outputExists)
			{
				session.ReportFilepaths.Add(filePath);
				session.Save();
				ListViewItem lvi = new ListViewItem(new string[] { filePath.ToString() });
				lvi.Tag = filePath;
				lbReportFiles.Items.Add(lvi);
			}
		}

		private void btnExportReportFile_Click(object sender, EventArgs e)
		{
			switch (cbExportReportTo.SelectedIndex)
			{
				case 0:
					// export selected report file to the PDF format
					for (int i = 0; i < lbReportFiles.SelectedItems.Count; i++)
					{
						if (lbReportFiles.SelectedItems[i] != null)
						{
							try
							{
								Excel.Workbook workbook = Globals.ThisAddIn.Application.Workbooks.Open(
												(lbReportFiles.SelectedItems[i].Tag as FilePath).FullPath,
												Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
												Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
												false, Type.Missing, Type.Missing, Type.Missing);

								string pdfFileName = Path.ChangeExtension((lbReportFiles.SelectedItems[i].Tag as FilePath).FullPath, ".pdf");

								workbook.ExportAsFixedFormat(Excel.XlFixedFormatType.xlTypePDF, pdfFileName, 0, true, false,
										System.Reflection.Missing.Value, System.Reflection.Missing.Value, true, System.Reflection.Missing.Value);

								workbook.Close(false, Type.Missing, Type.Missing);

								if (lbSessions.SelectedItem is Session)
									AddNewOutputToSession(lbSessions.SelectedItem as Session, pdfFileName);

								lbReportFiles.Select();
							}
							catch
							{
								MessageBox.Show("Cannot export file to PDF. Possibly you don't have the PDF Add-in for Office installed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
							}
						}
					}
					break;

				case 1:
					// export selected report file to the Word format
					for (int i = 0; i < lbReportFiles.SelectedItems.Count; i++)
					{
						if (lbReportFiles.SelectedItems[i] != null)
						{
							try
							{
								Excel.Workbook workbook = Globals.ThisAddIn.Application.Workbooks.Open(
												(lbReportFiles.SelectedItems[i].Tag as FilePath).FullPath,
												Type.Missing, true, Type.Missing, Type.Missing, Type.Missing,
												Type.Missing, Type.Missing, false, Type.Missing, Type.Missing,
												false, false, Type.Missing, Type.Missing);

								string wordFileName = Path.ChangeExtension((lbReportFiles.SelectedItems[i].Tag as FilePath).FullPath, ".docx");

								ExportForm exportForm = new ExportForm(workbook, wordFileName, ExportForm.ExportFormat.Word);

								exportForm.ShowDialog();

								workbook.Close(false, Type.Missing, Type.Missing);

								if (lbSessions.SelectedItem is Session)
									AddNewOutputToSession(lbSessions.SelectedItem as Session, wordFileName);

								lbReportFiles.Select();
							}
							catch
							{
								MessageBox.Show("Cannot export file to Word", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
							}
						}
					}

					break;

				case 2:
					for (int i = 0; i < lbReportFiles.SelectedItems.Count; i++)
					{
						if (lbReportFiles.SelectedItems[i] != null)
						{
							try
							{
								Excel.Workbook workbook = Globals.ThisAddIn.Application.Workbooks.Open(
												(lbReportFiles.SelectedItems[i].Tag as FilePath).FullPath, Type.Missing, true, Type.Missing,
												Type.Missing, Type.Missing, false, Type.Missing, Type.Missing,
												false, false, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

								string pptFileName = Path.ChangeExtension((lbReportFiles.SelectedItems[i].Tag as FilePath).FullPath, ".pptx");

								ExportForm exportForm = new ExportForm(workbook, pptFileName, ExportForm.ExportFormat.Powerpoint);

								exportForm.ShowDialog();

								workbook.Close(false, Type.Missing, Type.Missing);

								if (lbSessions.SelectedItem is Session)
									AddNewOutputToSession(lbSessions.SelectedItem as Session, pptFileName);

								lbReportFiles.Select();
							}
							catch
							{
								MessageBox.Show("Cannot export file to PowerPoint", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
							}
						}
					}

					break;
			}
		}

		private void btnNewReport_Click(object sender, EventArgs e)
		{
			if (lbLogFiles.Items.Count > 0)
				ShowWizard(DemoWizard.MainWizard.StartPage.Applications);
			else
				MessageBox.Show("There are no log files in the download folder");
		}

		private void btnExportLogFile_Click(object sender, EventArgs e)
		{
			for (int i = 0; i < lbLogFiles.SelectedItems.Count; i++)
			{
				if (lbLogFiles.SelectedItems[i] != null)
				{
					try
					{
						ExportToSQLWizard SQLWizard = new ExportToSQLWizard((lbLogFiles.SelectedItems[i].Tag as FilePath).FullPath);
						SQLWizard.ShowDialog();

						break;
					}
					catch
					{
						MessageBox.Show("Cannot export file to SQL. Possibly you don't have the PDF Add-in for Office installed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					}
				}
			}
		}
	}
}
